package com.jcl.recruit.wechat.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.jcl.core.utils.BaseUtils;
import com.jcl.core.utils.DateUtils;
import com.jcl.core.utils.EncodeMd;
import com.jcl.recruit.console.model.ConsoleUserAccess;
import com.jcl.recruit.core.config.SystemConfig;
import com.jcl.recruit.core.utils.RedisCacheUtils;
import com.jcl.recruit.user.model.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class WechatUtils {

    private static final Logger logger = LoggerFactory.getLogger(WechatUtils.class);



    public static final int express_in                           = 6700;

    public static final String APP_ID                            = "wx1543e58b5a0041cc";
    public static final String APP_SECRET                        = "aa70934e556a206ef27872b815e35213";

    public static final String LOGIN_STATE_SPLIT                 = "_";
    public static final String LOGIN_STATE                       = "fromWechat";
    public static final String LOGIN_STATE_INVITE                = "fromInvite";
    public static final String LOGIN_STATE_CRAWLER_DOWNLOAD      = "crawlerdownload";

    public static void main(String[] args) {


        String access_token = "15_PbqPtVXnPf3pEX2r954HK8OSJlvV3fYRjUlRC8ejIfZJuW36Y3caetg1BtbBoh6VtpyXUQPmGdpfAaJgDfjJV_G3mIc6jD4p40f1Zs5p_3zGcCrKXdgrIngdtyXAY2G7KPCx3yIMJs8WnKC9NDDfAGACSS";


    }


    public static WechatCodeMessage getCodeObject(String code) {
        JSONObject jsonObj = WeixinUtils.getCodeObjectJson(code);
        WechatCodeMessage obj = JSON.toJavaObject(jsonObj, WechatCodeMessage.class);
        return obj;
    }

    public static String getAccessToken() {
        String access_token = RedisCacheUtils.getWechatAccessToken();
        if(null == access_token){
            access_token = getNewAccessToken();
        }
        return access_token;
    }

    public static String getTicket() {
        String ticket = RedisCacheUtils.getWechatTicket();
        if(null == ticket){
            String access_token = getAccessToken();
            ticket = WeixinUtils.ticket(access_token);
            RedisCacheUtils.setWechatTicket(ticket);
        }
        return ticket;
    }

    public static WechatUserInfo getUserBaseInfoObject(String access_token, String openid) {
        JSONObject jsonObj = WeixinUtils.getUserBaseInfoObjectJson(access_token, openid);
        String accessToken = isSecondOperate(jsonObj);
        if(null != accessToken){
            jsonObj = WeixinUtils.getUserBaseInfoObjectJson(accessToken, openid);
        }
        WechatUserInfo obj = JSON.toJavaObject(jsonObj, WechatUserInfo.class);
        return obj;
    }

    public static WechatUserInfo getUserInfoObject(String access_token, String openid) {
        JSONObject jsonObj = WeixinUtils.getUserInfoObjectJson(access_token, openid);
        String accessToken = isSecondOperate(jsonObj);
        if(null != accessToken){
            jsonObj = WeixinUtils.getUserInfoObjectJson(accessToken, openid);
        }
        WechatUserInfo obj = JSON.toJavaObject(jsonObj, WechatUserInfo.class);
        return obj;
    }

    public static boolean sendTemplateMessage(String access_token, TemplateInfo info) {
        String message = info.toString();
        JSONObject jsonObject = WeixinUtils.sendTemplateMessageJson(access_token, message);
        String accessToken = isSecondOperate(jsonObject);
        if(null == accessToken){
            return true;
        }else{
            WeixinUtils.sendTemplateMessageJson(accessToken, message);
        }
        return WeixinUtils.JSON_OK.equals(jsonObject.getString(WeixinUtils.JSON_ERROR_MSG)) ? true : false;
    }

    public static long getOverTime() {
        Long times = System.currentTimeMillis() / 1000;
        return times + express_in;
    }

    public static String getWechatLoginUrl(String redirectUrl, String state) {
        return WeixinUtils.getWechatLoginUrl(SystemConfig.getSystemWechatAppid(), redirectUrl, state);
    }

    public static WechatCodeMessage refreshToken(String access_token) {
        JSONObject jsonObj = WeixinUtils.refreshToken(access_token);
        WechatCodeMessage obj = JSON.toJavaObject(jsonObj, WechatCodeMessage.class);
        return obj;
    }

    public static boolean validateAccessToken(String access_token, String openid) {
        JSONObject jsonObj = WeixinUtils.validateAccessToken(access_token, openid);
        boolean isTrue = WeixinUtils.JSON_OK.equals(jsonObj.getString(WeixinUtils.JSON_ERROR_MSG))
                ? true : false;
        return isTrue;
    }

    private static String isSecondOperate(JSONObject json){
        String accessToken = null;
        String errorCode = json.getString(WeixinUtils.JSON_ERROR_CODE);
        if(null != errorCode){
            if(WeixinUtils.ERROR_CODE_42001.equals(errorCode)
                    || WeixinUtils.ERROR_CODE_41001.equals(errorCode) ){
                accessToken = getNewAccessToken();
            }
        }
        return accessToken;
    }

    private static String getNewAccessToken() {
        String accessToken = WeixinUtils.getAccessToken();
        RedisCacheUtils.setWechatAccessToken(accessToken);
        return accessToken;
    }

    public static class AccessInfo {

        private String code;

        private String state;

        private String routerState;

        private String msg;

        private String userKey;

        private String accessId;

        private String accessKey;

        private Integer userStatus;

        private String userToken;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getUserKey() {
            return userKey;
        }

        public void setUserKey(String userKey) {
            this.userKey = userKey;
        }

        public String getAccessId() {
            return accessId;
        }

        public void setAccessId(String accessId) {
            this.accessId = accessId;
        }

        public String getAccessKey() {
            return accessKey;
        }

        public void setAccessKey(String accessKey) {
            this.accessKey = accessKey;
        }

        public String getState() {
            return state;
        }

        public void setState(String state) {
            this.state = state;
        }

        public String getRouterState() {
            return routerState;
        }

        public void setRouterState(String routerState) {
            this.routerState = routerState;
        }

        public Integer getUserStatus() {
            return userStatus;
        }

        public void setUserStatus(Integer userStatus) {
            this.userStatus = userStatus;
        }

        public String getUserToken() {
            return userToken;
        }

        public void setUserToken(String userToken) {
            this.userToken = userToken;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

    public static class AccessLoginInfo {

        private String code;
        private String msg;

        private User user;

        private ConsoleUserAccess userExternalAccess;

        private String openId;

        private Integer noUserAccessId;

        private Map<String, Integer> codeIdMap;


        public User getUser() {
            return user;
        }

        public void setUser(User user) {
            this.user = user;
        }

        public String getOpenId() {
            return openId;
        }

        public void setOpenId(String openId) {
            this.openId = openId;
        }

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public Integer getNoUserAccessId() {
            return noUserAccessId;
        }

        public void setNoUserAccessId(Integer noUserAccessId) {
            this.noUserAccessId = noUserAccessId;
        }

        public Map<String, Integer> getCodeIdMap() {
            return codeIdMap;
        }

        public void setCodeIdMap(Map<String, Integer> codeIdMap) {
            this.codeIdMap = codeIdMap;
        }

        public ConsoleUserAccess getUserExternalAccess() {
            return userExternalAccess;
        }

        public void setUserExternalAccess(ConsoleUserAccess userExternalAccess) {
            this.userExternalAccess = userExternalAccess;
        }
    }

    public static class TemplateScreenInfo {
        private Map<String, String> first = new HashMap<>();
        // 筛选内容
        private Map<String, String> keyword1 = new HashMap<>();
        // 通知人
        private Map<String, String> keyword2 = new HashMap<>();
        // 通知时间
        private Map<String, String> keyword3 = new HashMap<>();

        private Map<String, String> remark = new HashMap<>();

        public Map<String, String> getFirst() {
            return first;
        }

        public void setFirst(String first) {
            String _str = "根据推荐设置，为您推荐了" + first + "份简历,请您阅览";
            this.first.put("value", _str);
        }

        public void setCrawlingFirst(String first) {
            String _str = "今天爬取简历统计：\n\n " + first;
            this.first.put("value", _str);
            this.first.put("color", "#173177");
        }

        public Map<String, String> getKeyword1() {
            return keyword1;
        }

        public void setKeyword1(String keyword1) {
            this.keyword1.put("value", keyword1);
        }

        public Map<String, String> getKeyword2() {
            return keyword2;
        }

        public void setKeyword2(String keyword2) {
            this.keyword2.put("value", keyword2);
        }

        public Map<String, String> getKeyword3() {
            this.keyword3.put("value", DateUtils.format(new Date(), DateUtils.DATE_FORMAT_YMD));
            return keyword3;
        }

        public void setKeyword3(String keyword3) {

        }

        public Map<String, String> getRemark() {
            this.remark.put("value", "点击详情，查看筛选简历。");
            return remark;
        }

        public void setRemark(String remark) {

        }
    }

    public static class TemplateCrawlingCompleteInfo {

        private Map<String, String> first = new HashMap<>();
        // 筛选内容
        private Map<String, String> keyword1 = new HashMap<>();
        // 简历信息
        private Map<String, String> keyword2 = new HashMap<>();
        // 下载时间
        private Map<String, String> keyword3 = new HashMap<>();

        private Map<String, String> remark = new HashMap<>();

        public Map<String, String> getFirst() {
            return first;
        }

        public void setFirst(String first) {
            this.first.put("value", first);
        }

        public Map<String, String> getKeyword1() {
            return keyword1;
        }

        public void setKeyword1(String keyword1) {
            this.keyword1.put("value", keyword1);
        }

        public Map<String, String> getKeyword2() {
            return keyword2;
        }

        public void setKeyword2(String keyword2) {
            this.keyword2.put("value", keyword2);
        }

        public Map<String, String> getKeyword3() {

            return keyword3;
        }

        public void setKeyword3(Date keyword3) {
            this.keyword3.put("value", DateUtils.format(keyword3, DateUtils.DATE_FORMAT_YMDHM_CH));
        }

        public Map<String, String> getRemark() {
            return remark;
        }

        public void setRemark(String remark) {
            this.remark.put("value", remark);
        }
    }

    public static class TemplateInfo<T> {
        //public static final String screen_template_id = "PRit1w61F6iklsh4CasTtCeb3SCrNx2bC3HRKsPGPdY";
        private String touser;
        private String template_id;
        private String url;
        private T data;

        public String getTouser() {
            return touser;
        }

        public void setTouser(String touser) {
            this.touser = touser;
        }

        public String getTemplate_id() {
            return template_id;
        }

        public void setTemplate_id(String template_id) {
            this.template_id = template_id;
        }

        public String getUrl() {
            return url;
        }

        public void setUrl(String url) {
            this.url = url;
        }

        public T getData() {
            return data;
        }

        public void setData(T data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return JSON.toJSONString(this);
        }
    }

    public static class SignatureInfo {

        public static SignatureInfo initSignature(String url, String accessToken, String ticket) {
            SignatureInfo info = newInstance();
            info.setToken(accessToken);
            info.setJsapi_ticket(ticket);
            String decrypt = info.toSha1String(url);
            info.setSignature(EncodeMd.hexSHA1(decrypt));
            return info;
        }

        public String toSha1String(String url) {
            try {
                url = URLDecoder.decode(url, "UTF-8");
                url = url.split("#")[0];
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            StringBuffer str = new StringBuffer();
            str.append("jsapi_ticket=").append(jsapi_ticket)
                    .append("&noncestr=").append(nonceStr)
                    .append("&timestamp=").append(timestamp)
                    .append("&url=").append(url);

            return str.toString();
        }

        public static SignatureInfo newInstance() {
            SignatureInfo info = new SignatureInfo();
            info.setAppId(SystemConfig.getSystemWechatAppid());
            info.setSecret(SystemConfig.getSystemWechatAppsecret());
            info.setTimestamp(String.valueOf(System.currentTimeMillis() / 1000));
            info.setNonceStr(BaseUtils.randomString(20));
            return info;
        }

        private String timestamp;
        private String appId;
        private String secret;
        private String token;
        private String nonceStr;
        private String jsapi_ticket;

        private String signature;

        private SignatureInfo() {
        }

        public String getTimestamp() {
            return timestamp;
        }

        public void setTimestamp(String timestamp) {
            this.timestamp = timestamp;
        }

        public String getAppId() {
            return appId;
        }

        public void setAppId(String appId) {
            this.appId = appId;
        }

        public String getSecret() {
            return secret;
        }

        public void setSecret(String secret) {
            this.secret = secret;
        }

        public String getNonceStr() {
            return nonceStr;
        }

        public void setNonceStr(String nonceStr) {
            this.nonceStr = nonceStr;
        }

        public String getToken() {
            return token;
        }

        public void setToken(String token) {
            this.token = token;
        }

        public String getJsapi_ticket() {
            return jsapi_ticket;
        }

        public void setJsapi_ticket(String jsapi_ticket) {
            this.jsapi_ticket = jsapi_ticket;
        }

        public String getSignature() {
            return signature;
        }

        public void setSignature(String signature) {
            this.signature = signature;
        }
    }

    public static class WechatUserInfo {
        private String openid;
        private String nickname;
        private String sex;
        private String province;
        private String city;
        private String country;
        private String headimgurl;
        private List<String> privilege;
        private String unionid;
        private String corpCode;

        private String errcode;
        private String errmsg;

        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }

        public String getNickname() {
            return nickname;
        }

        public void setNickname(String nickname) {
            this.nickname = nickname;
        }

        public String getSex() {
            return sex;
        }

        public void setSex(String sex) {
            this.sex = sex;
        }

        public String getProvince() {
            return province;
        }

        public void setProvince(String province) {
            this.province = province;
        }

        public String getCity() {
            return city;
        }

        public void setCity(String city) {
            this.city = city;
        }

        public String getCountry() {
            return country;
        }

        public void setCountry(String country) {
            this.country = country;
        }

        public String getHeadimgurl() {
            return headimgurl;
        }

        public void setHeadimgurl(String headimgurl) {
            this.headimgurl = headimgurl;
        }

        public List<String> getPrivilege() {
            return privilege;
        }

        public void setPrivilege(List<String> privilege) {
            this.privilege = privilege;
        }

        public String getUnionid() {
            return unionid;
        }

        public void setUnionid(String unionid) {
            this.unionid = unionid;
        }

        public String getErrcode() {
            return errcode;
        }

        public void setErrcode(String errcode) {
            this.errcode = errcode;
        }

        public String getErrmsg() {
            return errmsg;
        }

        public void setErrmsg(String errmsg) {
            this.errmsg = errmsg;
        }

        public String getCorpCode() {
            return corpCode;
        }

        public void setCorpCode(String corpCode) {
            this.corpCode = corpCode;
        }
    }

    public static class WechatCodeMessage {

        private String access_token;
        private String refresh_token;
        private String openid;
        private String scope;
        private Integer expires_in;

        private String errcode;
        private String errmsg;

        public String getAccess_token() {
            return access_token;
        }

        public void setAccess_token(String access_token) {
            this.access_token = access_token;
        }

        public String getRefresh_token() {
            return refresh_token;
        }

        public void setRefresh_token(String refresh_token) {
            this.refresh_token = refresh_token;
        }

        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }

        public String getScope() {
            return scope;
        }

        public void setScope(String scope) {
            this.scope = scope;
        }

        public Integer getExpires_in() {
            return expires_in;
        }

        public void setExpires_in(Integer expires_in) {
            this.expires_in = expires_in;
        }

        public String getErrcode() {
            return errcode;
        }

        public void setErrcode(String errcode) {
            this.errcode = errcode;
        }

        public String getErrmsg() {
            return errmsg;
        }

        public void setErrmsg(String errmsg) {
            this.errmsg = errmsg;
        }
    }

}
